﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CTP.Session;
using CTP.Command;
using CTP.Entitys;
using System.Runtime.InteropServices;
using CTP.Utilty;
using CTP.Exceptions;

namespace CTP
{

    /// <summary>
    /// 功能：实现COM接口，接收客户系统的调用，把客户系统的调用转发到参数指定的资
    ///       金账号的Session中。
    /// 创建：陈粤雄 20120428
    /// </summary>
    [ClassInterface(ClassInterfaceType.None)]
    [Guid("b4eef2a6-fc19-4e91-8cb4-609c87c0e2a6")]
    public class CCTP : ICTP, IDisposable
    {
        public CCTP()
        {
            Logger.Instance.WriteInfo("CCTP正在启动...");
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
        }

        public void Dispose()
        {
            AppDomain.CurrentDomain.UnhandledException -= new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
        }

        /// <summary>
        /// 处理未处理的异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            ReturnInfo info = ReturnInfo.Create(false, ErrorCode.UnHandle, e.ExceptionObject.ToString());
            Logger.Instance.WriteError("未处理的异常：" + e.ExceptionObject);
        }

        /// <summary>
        /// 注册回调接口
        /// </summary>
        /// <param name="iCTPCallback"></param>
        /// <returns></returns>
        [ComVisible(false)]
        public void RegisterCallback(ICTPCallbackHandle callback)
        {
            Logger.Instance.WriteInfo("正在注册回调接口...");
            if (callback == null)
            {
                Logger.Instance.WriteInfo("没能成功注册回调接口，要注册的回调接口实例为null");
            }
            else
            {
                ResponseManager.Instance.RegisterCallback(callback);
                Logger.Instance.WriteInfo("已注册回调接口，类型：{0}" + callback.GetType().FullName);
            }
        }

        /// <summary>
        /// 卸载回调
        /// </summary>
        /// <param name="tradingAccount"></param>
        [ComVisible(false)]
        public void UnRegisterCallback(ICTPCallbackHandle callback)
        {
            Logger.Instance.WriteInfo("正在卸载回调接口...");
            if (callback == null)
            {
                Logger.Instance.WriteInfo("没能成功卸载回调接口，资金账号为空");
            }
            else
            {
                ResponseManager.Instance.UnRegisterCallback(callback);
                Logger.Instance.WriteInfo("已卸载回调接口：{0}" + callback.ToString());
            }
        }

        #region 下单
        /// <summary>
        /// 资金账号登陆
        /// </summary>
        /// <param name="account"></param>
        /// <param name="requestId"></param>
        public int Login(TradingAccount account, int requestId)
        {
            LoginCmd cmd = new LoginCmd()
            {
                RequestID = requestId,
                TradingAccount = account
            };

            return sendCmd(account.UserAccount, cmd);
        }

        /// <summary>
        /// 登出资金账号
        /// </summary>
        /// <param name="account"></param>
        /// <param name="requestId"></param>
        public int Logout(TradingAccount account, int requestId)
        {
            LogoutCmd cmd = new LogoutCmd()
            {
                RequestID = requestId,
                TradingAccount = account
            };

            return sendCmd(account.UserAccount, cmd);
        }

        /// <summary>
        /// 查询结算信息(帐户概览)
        /// </summary>
        /// <param name="account"></param>
        /// <param name="requestId"></param>
        public int QuerySettlement(TradingAccount account, int requestId)
        {
            QuerySettlementCmd cmd = new QuerySettlementCmd()
            {
                RequestID = requestId,
                TradingAccount = account
            };

            return sendCmd(account.UserAccount, cmd);
        }

        /// <summary>
        /// 确认资金账号信息
        /// </summary>
        /// <param name="account"></param>
        /// <param name="requestId"></param>
        public int ConfirmSettlement(TradingAccount account, int requestId)
        {
            ConfirmSettlementCmd cmd = new ConfirmSettlementCmd()
            {
                RequestID = requestId,
                TradingAccount = account
            };

            return sendCmd(account.UserAccount, cmd);
        }

        /// <summary>
        /// 查询帐户概览
        /// </summary>
        /// <param name="account"></param>
        /// <param name="requestId"></param>
        public int QueryAccountSummary(TradingAccount account, int requestId)
        {
            QueryAccountSummaryCmd cmd = new QueryAccountSummaryCmd()
            {
                RequestID = requestId,
                TradingAccount = account
            };

            return sendCmd(account.UserAccount, cmd);
        }

        /// <summary>
        /// 下单
        /// </summary>
        /// <param name="account"></param>
        /// <param name="ord"></param>
        /// <param name="requestId"></param>
        public int PlaceOrder(TradingAccount account, Order ord, int requestId)
        {
            Logger.Instance.WriteDebug(string.Format("已收到下单指令，requestId={0},code={1}", requestId, ord.Code));
            PlaceOrderCmd cmd = new PlaceOrderCmd()
            {
                RequestID = requestId,
                TradingAccount = account,
                Order = ord
            };

            return sendCmd(account.UserAccount, cmd);
        }

        /// <summary>
        /// 查询委托单状态
        /// </summary>
        /// <param name="account"></param>
        /// <param name="ord"></param>
        /// <param name="requestId"></param>
        public int QueryOrderStatus(TradingAccount account, Order ord, int requestId)
        {
            QueryOrderStatusCmd cmd = new QueryOrderStatusCmd()
            {
                RequestID = requestId,
                TradingAccount = account,
                Order = ord
            };

            return sendCmd(account.UserAccount, cmd);
        }

        /// <summary>
        /// 撤单
        /// </summary>
        /// <param name="account"></param>
        /// <param name="ord"></param>
        /// <param name="requestId"></param>
        public int CancelOrder(TradingAccount account, CancelOrderInfo order, int requestId)
        {
            CancelOrderCmd cmd = new CancelOrderCmd()
            {
                RequestID = requestId,
                TradingAccount = account,
                CancelOrderInfo = order
            };

            return sendCmd(account.UserAccount, cmd);
        }

        /// <summary>
        /// 查询当天委托
        /// </summary>
        /// <param name="account"></param>
        /// <param name="page"></param>
        /// <param name="requestId"></param>
        public int QueryTodayOrder(TradingAccount account, PageInfo page, int requestId)
        {
            QueryTodayOrderRequestCmd cmd = new QueryTodayOrderRequestCmd()
            {
                RequestID = requestId,
                TradingAccount = account,
                PageInfo = page
            };

            return sendCmd(account.UserAccount, cmd);
        }

        /// <summary>
        /// 查询今日成交
        /// </summary>
        /// <param name="account"></param>
        /// <param name="page"></param>
        /// <param name="requestId"></param>
        public int QueryTodayFilled(TradingAccount account, PageInfo page, int requestId)
        {
            QueryTodayFilledCmd cmd = new QueryTodayFilledCmd()
            {
                RequestID = requestId,
                TradingAccount = account
            };

            return sendCmd(account.UserAccount, cmd);
        }

        /// <summary>
        /// 查询持仓
        /// </summary>
        /// <param name="account"></param>
        /// <param name="requestId"></param>
        public int QueryPosition(TradingAccount account, int requestId)
        {
            QueryPositionCmd cmd = new QueryPositionCmd()
            {
                RequestID = requestId,
                TradingAccount = account
            };

            return sendCmd(account.UserAccount, cmd);
        }

        public bool GetIsLogined(string account)
        {
            Session.Session session = SessionManager.Instance.GetSession(account);

            return session != null && session.IsLogined;
        }

        public bool GetIsConnected(string account)
        {
            Session.Session session = SessionManager.Instance.GetSession(account);

            return session != null && session.IsConnected;
        }

        /// <summary>
        /// 发送命令
        /// </summary>
        /// <param name="account"></param>
        /// <param name="cmd"></param>
        /// <returns></returns>
        private int sendCmd(string account, IRequestCommand cmd)
        {
            if (string.IsNullOrEmpty(account))
                return -1;

            // 获取一个会话
            Session.Session session = SessionManager.Instance.GetSession(account);
            if (session == null)
            {
                // 如果没有建立相应资金账号的会话，则新建一个会话
                session = new Session.Session(account);
                SessionManager.Instance.Add(account, session);
            }

            // 发送命令
            return session.Excute(cmd);
        }
        #endregion

        #region 行情
        /// <summary>
        /// 登陆行情
        /// </summary>
        /// <param name="account"></param>
        /// <param name="requestId"></param>
        /// <returns></returns>
        public int LoginQoute(TradingAccount account, int requestId)
        {
            isSendLogined = true;
            return QouteSession.Instance.Login(account, requestId);
        }

        /// <summary>
        /// 登出行情
        /// </summary>
        /// <param name="account"></param>
        /// <param name="requestId"></param>
        /// <returns></returns>
        public int LogoutQoute(TradingAccount account, int requestId)
        {
           int res= checkState();
           if (res != ErrorCode.Success)
               return res;

            return QouteSession.Instance.Logout(account, requestId);
        }

        /// <summary>
        /// 订阅行情
        /// </summary>
        /// <param name="codes"></param>
        /// <returns></returns>
        public int SubscribeQoute(string[] codes)
        {
            int res = checkState();
            if (res != ErrorCode.Success)
                return res;

            if (codes == null || codes.Length < 1)
                return ErrorCode.UnHandle;

            return QouteSession.Instance.SubscribeQoute(codes);
        }

        /// <summary>
        /// 取消订阅
        /// </summary>
        /// <param name="codes"></param>
        /// <returns></returns>
        public int UnSubscribeQoute(string[] codes)
        {
            int res = checkState();
            if (res != ErrorCode.Success)
                return res;

            if (codes == null || codes.Length < 1)
                return ErrorCode.UnHandle;

            return QouteSession.Instance.UnSubscribeQoute(codes);
        }

        /// <summary>
        /// 获取行情指定账号是否已登陆
        /// </summary>
        /// <param name="account"></param>
        /// <returns></returns>
        public bool GetQouteIsLogined(string account)
        {
            return QouteSession.Instance.IsLogined;
        }

        /// <summary>
        /// 获取行情指定账号是否已连接
        /// </summary>
        /// <param name="account"></param>
        /// <returns></returns>
        public bool GetQouteIsConnected(string account)
        {
            return QouteSession.Instance.IsConnected;
        }

        private int checkState()
        {
            if (!isSendLogined)
                return ErrorCode.NotLogin;
            else
                return ErrorCode.Success;
        }
        private bool isSendLogined = false;
        #endregion

    }
}
